package com.zoro.dyformservice.support.http;

import com.zoro.dyformservice.support.ex.BusinessException;
import com.zoro.dyformservice.utils.JsonUtil;
import com.zoro.dyformservice.utils.StringUtils;
import jakarta.servlet.http.HttpServletResponse;
import okhttp3.*;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import java.io.IOException;
import java.lang.reflect.Type;
import java.time.Duration;
import java.util.*;

public class CommonHttpClient {

    private final static String HEADER_AUTHORIZATION = "Authorization";
    private final static String HEADER_AUTHORIZATION_PREFIX = "Basic ";

    private final static OkHttpClient OK_HTTP;

    static {
        Dispatcher dispatcher = new Dispatcher();
        dispatcher.setMaxRequests(2000);
        dispatcher.setMaxRequestsPerHost(2000);
        OK_HTTP = new OkHttpClient.Builder()
                .callTimeout(Duration.ofSeconds(10))
                .dispatcher(dispatcher)
                .build();
    }


    private static String basicAuthString(String auth){
        if (auth.startsWith(HEADER_AUTHORIZATION_PREFIX)){
            return auth;
        } else {
            return HEADER_AUTHORIZATION_PREFIX+ auth;
        }
    }

    public static String basicAuthPost(String url, String basicString, Object body, Map<String, String> headers) throws Exception {

        Request.Builder builder = new Request.Builder()
                .url(url)
                .header(HEADER_AUTHORIZATION, basicAuthString(basicString));
        if (body != null) {
            RequestBody requestBody = RequestBody.create(JsonUtil.toBytes(body));
            builder.post(requestBody);
        } else {
            builder.method("POST", RequestBody.create(JsonUtil.toBytes(null)));
        }
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, String> head : headers.entrySet()) {
                builder.header(head.getKey(), head.getValue());
            }
        }
        try (Response response = OK_HTTP.newCall(builder.build()).execute()) {
            if (!response.isSuccessful()) {
                throw new RuntimeException("请求出错(POST), url: " + url + "," + response);
            }
            return response.body() == null ? null : response.body().string();
        }
    }

    public static <T> T basicAuthPost(String url, String basicString, Object body, Map<String, String> headers,
                                      Type responseType) throws Exception {
        String result = basicAuthPost(url, basicString, body, headers);
        if (result == null) {
            return null;
        }
        return JsonUtil.toJavaType(result, responseType);
    }

    public static <T> T basicAuthPostJson(String url, String basicString, Object body, Type responseType) throws Exception {
        Map<String, String> header = new HashMap<>();
        header.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
        return basicAuthPost(url, basicString, body, header, responseType);
    }

    public static String basicAuthGet(String url, String basicString, Map<String, List<String>> queryParam) throws IOException {

        String queryString = makeQueryParam(queryParam);

        Request.Builder builder = new Request.Builder()
                .url(url + queryString)
                .get()
                .header(HEADER_AUTHORIZATION, basicAuthString(basicString));

        try (Response response = OK_HTTP.newCall(builder.build()).execute()) {
            if (!response.isSuccessful()) {
                if (response.code() == HttpServletResponse.SC_UNAUTHORIZED) {
                    throw new BusinessException("认证失败");
                }
                throw new RuntimeException("请求出错(GET), url: " + url + "," + response);
            }
            return response.body() == null ? null : response.body().string();
        }
    }

    public static <T> T basicAuthGet(String url, String basicString, Type responseType) throws IOException {
        String result = basicAuthGet(url, basicString, (Map<String, List<String>>) null);
        if (result == null) {
            return null;
        }
        return JsonUtil.toJavaType(result, responseType);
    }


    public static <T> T basicAuthGet(String url, String basicString, Map<String, List<String>> queryParam,
                                     Type responseType) throws IOException {
        String result = basicAuthGet(url, basicString, queryParam);
        if (result == null) {
            return null;
        }
        return JsonUtil.toJavaType(result, responseType);
    }

    private static String makeQueryParam(Map<String, List<String>> queryParams) {
        if (queryParams == null || queryParams.isEmpty()) {
            return "";
        }
        Set<Map.Entry<String, List<String>>> entries = queryParams.entrySet();
        List<String> keyValuePair = new ArrayList<>();
        for (Map.Entry<String, List<String>> entry : entries) {
            List<String> values = entry.getValue();
            String key = entry.getKey();
            if (StringUtils.isNotBlank(key)) {
                continue;
            }
            if (values == null || values.size() == 0) {
                keyValuePair.add(key + "=");
                continue;
            }
            for (String value : values) {
                keyValuePair.add(key + "=" + (value == null ? "" : value));
            }
        }
        return "?" + StringUtils.join(keyValuePair);
    }
}
